{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Zynq Ultrascale+ DisplayPort output\n",
    "\n",
    "This notebook introduces using the DisplayPort output of the Zynq Ultrascale+ through PYNQ. By default we don't start X and instead provide a lower-level API to match the HDMI API we provide for the PYNQ-Z1 board.\n",
    "\n",
    "To start with we import the `video` library which contains the `DisplayPort` class and supporting helper classes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [],
   "source": [
    "from pynq.lib.video import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we create a `DisplayPort` object and configure it with the resolution and pixel format we would like."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "displayport = DisplayPort()\n",
    "\n",
    "displayport.configure(VideoMode(1280, 720, 24), PIXEL_RGB)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now test the output by setting the blue pixel of the frame in a loop and outputting the loop. From this we can see that the loop easily runs at 60 frames per second."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Took 10.003438472747803 seconds at 59.97937625493172 FPS\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "start = time.time()\n",
    "\n",
    "for i in range(600):\n",
    "    frame = displayport.newframe()\n",
    "    frame[:,:,0] = i % 256\n",
    "    displayport.writeframe(frame)\n",
    "    \n",
    "end = time.time()\n",
    "duration = end - start\n",
    "print(f\"Took {duration} seconds at {600 / duration} FPS\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It's far more exciting though to show an image from a webcam. We can do this using OpenCV. First we need to instantiate the `VideoCapture` device and set the resolution to match our frame.\n",
    "\n",
    "For the next cell, make sure you have a webcam plugged into one of the USB ports."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "os.environ[\"OPENCV_LOG_LEVEL\"]=\"SILENT\"\n",
    "import cv2\n",
    "\n",
    "capture = cv2.VideoCapture(0)\n",
    "\n",
    "capture.set(3, 1280)\n",
    "capture.set(4, 720)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then we can do a similar loop and record the framerate. This is slower due to the overhead in capturing frames from the camera."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Took 22.52149271965027 seconds at 6.660304530752672 FPS\n"
     ]
    }
   ],
   "source": [
    "number_frames = 150\n",
    "start = time.time()\n",
    "\n",
    "for _ in range(number_frames):\n",
    "    frame = displayport.newframe()\n",
    "    capture.read(frame)\n",
    "    displayport.writeframe(frame)\n",
    "\n",
    "end = time.time()\n",
    "duration = end - start\n",
    "print(f\"Took {duration} seconds at {number_frames / duration} FPS\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally we need to close the devices."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "capture.release()\n",
    "displayport.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
